#include <iostream>
#include <string>
#include <vector>
#include <unistd.h>
#include <sys/types.h>
#include "Task.hpp"
#include <sys/wait.h>

//master视角
class Channel
{
public:
    Channel(int wfd,pid_t subprocessid,std::string& name)
        :_wfd(wfd),_subprocessid(subprocessid),_name(name)
    {}

    ~Channel()
    {}

    std::string GetName()
    {
        return _name;
    }

    int GetProcessid()
    {
        return _subprocessid;
    }

    int GetWfd()
    {
        return _wfd;
    }
    void CloseChannel()
    {
        close(_wfd);
    }

    void Wait()
    {
        int rid = waitpid(_subprocessid,nullptr,0);
        if(rid > 0)
        {
            std::cout<<"wait " << rid << "sucess" << std::endl;
        }
    }
protected:
    int _wfd;
    pid_t _subprocessid;
    std::string _name;
};

// void work(int rfd)
// {
//     while(true)
//     {
//         int command = 0;
//         int n = read(rfd,&command,sizeof command);
//         if(n == sizeof(int))
//         {
//             std::cout<<"pid is:"<<getpid()<<"hander task"<<std::endl;
//             ExcuteTask(command);
//         }
//         else if(n == 0)
//         {
//             std::cout<<"sub process: "<<getpid()<<"quit" << std::endl;
//             break;
//         }
//     }

// }



int NextChannel(int channelnum)
{
    static int next = 0;
    int channel = next;
    next++;
    next %= channelnum;
    return channel;
}

void CreatChannelAndProcess(int num,std::vector<Channel>* channels,task_t task)
{
//const &:输入型参数
//& : 输入输出型参数
//* : 输出型参数
    for(int i = 0 ; i < num ; i++)
    {
        //1.1 创建管道
        int pipefd[2];
        int n = pipe(pipefd);
        if(n < 0)
            exit(1);

        //1.2 创建子进程
        pid_t id = fork();
        if(id == 0)
        {
            if(!channels->empty())
            {
                for(auto& channel : *channels)
                    channel.CloseChannel();
            }
            //Child  ->  read
            close(pipefd[1]);
            dup2(pipefd[0] , 0);
            task();
            close(pipefd[0]);
            exit(0);
        }
        //Father  -> write
        close(pipefd[0]);
        
        //1.3 管理信道
        std::string name = "Channels-" + std::to_string(i);
        channels->push_back(Channel(pipefd[1] , id , name));
    }
}

void SendTaskCommand(Channel& channels,int taskcommand)
{
    write(channels.GetWfd() , &taskcommand,sizeof taskcommand);
}

void CtrlProcessOnce(std::vector<Channel>& channels)
{
    sleep(1);
    //2.1 选择任务
    int taskcommand = SelectTask();
    //2.2 选择信道和进程
    int channel_index = NextChannel(channels.size());
    //2.3 发送任务
    SendTaskCommand(channels[channel_index] , taskcommand);
    std::cout<<std::endl;
    std::cout<<"taskcommand: "<<taskcommand\
    <<"  channel: "<<channels[channel_index].GetName()<<" sub process: "<<channels[channel_index].GetProcessid()<<std::endl;
}

void CtrlProcess(std::vector<Channel>& channels,int times = -1)
{
    if(times > 0)
    {
        while(times--)
        {
            CtrlProcessOnce(channels);
        }
    }
    else
    {
        while(true)
        {
            CtrlProcessOnce(channels);
        }
    }
}

void CleanUpChannel(std::vector<Channel>& channels)
{
    //3.1 关闭写端wfd, 子进程read 读到0。
    // for(auto& channel : channels)
    // {
    //     channel.CloseChannel();
    // }
    // //3.2 等待子进程，进行回收
    // for(auto& channel : channels)
    // {
    //     channel.Wait();
    // }

    for(auto& channel : channels)
    {
        channel.CloseChannel();
        channel.Wait();        
    }

}

int main(int argc,char* argv[])
{
    if(argc != 2)
    {
        std::cerr<<"Usage: " << argv[0] << " processnum" << std::endl;
        return 1;
    }
    int num = std::stoi(argv[1]);
    LoadTask();

    //1. 创建信道和子进程
    std::vector<Channel> channels;
    CreatChannelAndProcess(num,&channels,work);

    //2. 通过Channel控制子进程
    CtrlProcess(channels,5);
    
    //3. 关闭管道,等待回收子进程
    CleanUpChannel(channels);

    return 0;
}